package database

import (
	"context"
	"database/sql"
	"fmt"
	"sync"
	"time"

	"oracle-mcp-server/internal/config"
)

// PoolManager 连接池管理器
type PoolManager struct {
	db     *sql.DB
	config config.DatabaseConfig
	stats  *PoolStats
	mu     sync.RWMutex
}

// PoolStats 连接池统计信息
type PoolStats struct {
	MaxOpenConnections int           `json:"max_open_connections"`
	OpenConnections    int           `json:"open_connections"`
	InUse              int           `json:"in_use"`
	Idle               int           `json:"idle"`
	WaitCount          int64         `json:"wait_count"`
	WaitDuration       time.Duration `json:"wait_duration"`
	MaxIdleClosed      int64         `json:"max_idle_closed"`
	MaxIdleTimeClosed  int64         `json:"max_idle_time_closed"`
	MaxLifetimeClosed  int64         `json:"max_lifetime_closed"`
}

// NewPoolManager 创建新的连接池管理器
func NewPoolManager(db *sql.DB, cfg config.DatabaseConfig) *PoolManager {
	return &PoolManager{
		db:     db,
		config: cfg,
		stats:  &PoolStats{},
	}
}

// GetStats 获取连接池统计信息
func (pm *PoolManager) GetStats() *PoolStats {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	dbStats := pm.db.Stats()
	
	pm.stats.MaxOpenConnections = dbStats.MaxOpenConnections
	pm.stats.OpenConnections = dbStats.OpenConnections
	pm.stats.InUse = dbStats.InUse
	pm.stats.Idle = dbStats.Idle
	pm.stats.WaitCount = dbStats.WaitCount
	pm.stats.WaitDuration = dbStats.WaitDuration
	pm.stats.MaxIdleClosed = dbStats.MaxIdleClosed
	pm.stats.MaxIdleTimeClosed = dbStats.MaxIdleTimeClosed
	pm.stats.MaxLifetimeClosed = dbStats.MaxLifetimeClosed

	return pm.stats
}

// HealthCheck 检查连接池健康状态
func (pm *PoolManager) HealthCheck(ctx context.Context) error {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	// 检查数据库连接
	if err := pm.db.PingContext(ctx); err != nil {
		return fmt.Errorf("数据库连接检查失败: %w", err)
	}

	// 检查连接池状态
	stats := pm.db.Stats()
	
	// 如果等待连接的时间过长，可能存在问题
	if stats.WaitDuration > time.Second*5 {
		return fmt.Errorf("连接池等待时间过长: %v", stats.WaitDuration)
	}

	// 如果所有连接都在使用中，可能需要增加连接数
	if stats.InUse >= stats.MaxOpenConnections {
		return fmt.Errorf("连接池已满，考虑增加最大连接数")
	}

	return nil
}

// OptimizePool 根据当前使用情况优化连接池配置
func (pm *PoolManager) OptimizePool() {
	pm.mu.Lock()
	defer pm.mu.Unlock()

	stats := pm.db.Stats()
	
	// 如果等待时间过长且连接数未达到上限，建议增加连接数
	if stats.WaitDuration > time.Second*2 && stats.OpenConnections < pm.config.MaxOpenConns {
		// 这里可以记录建议，实际调整需要重启应用
		fmt.Printf("建议增加最大连接数，当前等待时间: %v\n", stats.WaitDuration)
	}

	// 如果空闲连接过多，建议减少空闲连接数
	if stats.Idle > pm.config.MaxIdleConns/2 && pm.config.MaxIdleConns > 2 {
		fmt.Printf("空闲连接较多，当前空闲: %d，建议减少最大空闲连接数\n", stats.Idle)
	}
}

// ExecuteWithTimeout 带超时的查询执行
func (pm *PoolManager) ExecuteWithTimeout(ctx context.Context, query string, timeout time.Duration, args ...interface{}) (*sql.Rows, error) {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	// 创建带超时的上下文
	timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	// 执行查询
	rows, err := pm.db.QueryContext(timeoutCtx, query, args...)
	if err != nil {
		return nil, fmt.Errorf("查询执行失败: %w", err)
	}

	return rows, nil
}

// ExecuteTransactionWithTimeout 带超时的事务执行
func (pm *PoolManager) ExecuteTransactionWithTimeout(ctx context.Context, timeout time.Duration, fn func(*sql.Tx) error) error {
	pm.mu.RLock()
	defer pm.mu.RUnlock()

	// 创建带超时的上下文
	timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
	defer cancel()

	// 开始事务
	tx, err := pm.db.BeginTx(timeoutCtx, nil)
	if err != nil {
		return fmt.Errorf("开始事务失败: %w", err)
	}

	// 确保事务被正确处理
	defer func() {
		if p := recover(); p != nil {
			tx.Rollback()
			panic(p)
		}
	}()

	// 执行事务函数
	if err := fn(tx); err != nil {
		if rbErr := tx.Rollback(); rbErr != nil {
			return fmt.Errorf("事务回滚失败: %v, 原始错误: %w", rbErr, err)
		}
		return err
	}

	// 提交事务
	if err := tx.Commit(); err != nil {
		return fmt.Errorf("事务提交失败: %w", err)
	}

	return nil
}